#define NANOPRINTF_CONVERSION_BUFFER_SIZE    512
#define NANOPRINTF_CONVERSION_FLOAT_TYPE    uint64_t

#include "unit_ftoa_rev.cc"

TEST_CASE("ftoa_rev_64") {
  memset(&spec, 0, sizeof(spec));

  SUBCASE("integer overflow") {
    spec.prec = 1;
    require_ftoa_rev("2251799813685247.3", ((npf_double_bin_t)0x1 << (DBL_MANT_DIG - 2)) - 1 + 0.25);
    require_ftoa_rev("2251799813685247.5", ((npf_double_bin_t)0x1 << (DBL_MANT_DIG - 2)) - 1 + 0.5);
    require_ftoa_rev("2251799813685247.8", ((npf_double_bin_t)0x1 << (DBL_MANT_DIG - 2)) - 1 + 0.75);
    require_ftoa_rev("4503599627370495.5", ((npf_double_bin_t)0x1 << (DBL_MANT_DIG - 1)) - 1 + 0.5);
    require_ftoa_rev("9007199254740991.0", ((npf_double_bin_t)0x1 << DBL_MANT_DIG) - 1);
    require_ftoa_rev("18446744073709549568.0", (npf_double_bin_t)-1 << (NPF_DOUBLE_BIN_BITS - DBL_MANT_DIG));
  }

  SUBCASE("fraction accuracy") {
    spec.prec = 53 + 3;
    require_ftoa_rev("1.00000000000000022204460492503130808472633361816406250000", 1. + 1. / ((npf_double_bin_t)0x1 << NPF_DOUBLE_MAN_BITS));
    require_ftoa_rev("0.99999999999999988897769753748434595763683319091796875000", 1. - 1. / ((npf_double_bin_t)0x1 << DBL_MANT_DIG));
    require_ftoa_rev("0.66666666666666662965923251249478198587894439697265625000", 2. / 3.);
    require_ftoa_rev("0.00000000000000000000066666666666666663633791789500548930", 2. / 3. / 1e21);
  }

  SUBCASE("limits") {
    // largest representable number
    require_ftoa_rev_bin(
      "17976931348623156688000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "000000000000000000000000000000000000000000000000000000000000000000000",
      ((npf_double_bin_t)NPF_DOUBLE_EXP_MASK << NPF_DOUBLE_MAN_BITS) - 1);

    spec.prec = 384 + 3;

    // smallest normal number
    require_ftoa_rev_bin(
      "0.000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000022250738585"
      "072013598145646007253617426613345742225646972656250000000000000000000",
      (npf_double_bin_t)0x1 << NPF_DOUBLE_MAN_BITS);

    // largest subnormal number
    require_ftoa_rev_bin(
      "0.000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000022250738585"
      "072008645510122093469362880568951368331909179687500000000000000000000",
      ((npf_double_bin_t)0x1 << NPF_DOUBLE_MAN_BITS) - 1);

    // smallest representable numbers
    require_ftoa_rev_bin(
      "0.000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "000014821969375237396167321879403289131005294620990753173828125000000",
      (npf_double_bin_t)0x3 << 0);

    require_ftoa_rev_bin(
      "0.000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "000009881312916824930773877777578917402934166602790355682373046875000",
      (npf_double_bin_t)0x2 << 0);

    require_ftoa_rev_bin(
      "0.000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
      "000004940656458412465387372569658452903240686282515525817871093750000",
      (npf_double_bin_t)0x1 << 0);
  }
}
